﻿//-----------------------------------------------------------------------
// <copyright file="ConfigurableIntrospectionRule!1.cs">
//     Copyright (c) Nicole Calinoiu. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml;

using Microsoft.FxCop.Sdk;

namespace Bordecal.FxCop.Sdk
{
	/// <summary>
	/// Base class for configurable introspection rules.
	/// </summary>
	/// <typeparam name="TConfiguration">The configuration type.</typeparam>
	public abstract class ConfigurableIntrospectionRule<TConfiguration> : IntrospectionRule, IConfigurableRule
		where TConfiguration : IRuleConfiguration, new()
	{
		#region Fields

		private readonly TConfiguration _defaultConfiguration;

		#endregion

		#region Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="ConfigurableIntrospectionRule{TConfiguration}"/> class.
		/// </summary>
		/// <param name="descriptor">The <see cref="IRuleDescriptor"/> for the rule.</param>
		protected ConfigurableIntrospectionRule(IRuleDescriptor descriptor)
			: base(descriptor)
		{
			this._defaultConfiguration = new TConfiguration();

			TConfiguration currentConfiguration = (TConfiguration)RuleConfigurations.GetConfiguration(this);
			if (currentConfiguration == null)
			{
				currentConfiguration = new TConfiguration();
			}

			this.CurrentConfiguration = currentConfiguration;
		}

		#endregion

		#region Properties

		/// <summary>
		/// Gets the default configuration for the rule.
		/// </summary>
		protected TConfiguration DefaultConfiguration
		{
			get
			{
				return this._defaultConfiguration;
			}
		}

		/// <summary>
		/// Gets the current configuration for the rule.
		/// </summary>
		protected TConfiguration CurrentConfiguration { get; private set; }

		#endregion

		#region IConfigurableRule Members

		/// <summary>
		/// Gets the default rule settings.
		/// </summary>
		public IDictionary DefaultSettings
		{
			get
			{
				return this._defaultConfiguration.Settings;
			}
		}

		/// <summary>
		/// Gets the current rule settings.
		/// </summary>
		public IDictionary Settings
		{
			get
			{
				return this.CurrentConfiguration.Settings;
			}
		}

		/// <summary>
		/// Loads the rule settings from an FxCop project file.
		/// </summary>
		/// <param name="node">The source settings node.</param>
		public void LoadSettings(XmlNode node)
		{
			ConfigurationHelper.LoadSettings(this, node);
			this.CurrentConfiguration.LoadFromDictionary((Dictionary<string, string>)this.Settings);

			RuleConfigurations.SetConfiguration(this, this.CurrentConfiguration);
		}

		/// <summary>
		/// Saves the rule settings to an FxCop project file.
		/// </summary>
		/// <param name="writer">The target <see cref="XmlWriter"/>.</param>
		public void SaveSettings(XmlWriter writer)
		{
			if (writer == null)
			{
				throw new ArgumentNullException("writer");
			}
			
			ConfigurationHelper.SaveSettings(this, writer);
		}

		#endregion
	}
}